﻿using System;
using System.Linq;
using System.Threading.Tasks;

namespace ElevatorDispatching
{

    /// <summary>
    /// 呼层呼梯信号处理器的基本实现
    /// </summary>
    public abstract class SignalHandlerBase : ISignalHandler
    {
        /// <summary>
        /// 与处理器关联的楼层群组
        /// </summary>
        protected IFloorGroup Floors { get; }

        /// <summary>
        /// 与处理器关联的电梯群组
        /// </summary>
        protected IElevatorGroup Elevators { get; }

        public SignalHandlerBase(IFloorGroup floors, IElevatorGroup elevators)
        {
            Floors = floors;
            Elevators = elevators;
        }

        /// <summary>
        /// 呼层呼梯信号的默认实现，将呼层呼梯信号分别交由各自的方法来处理。
        /// <seealso cref="HandleCallFloorSignal(Elevator, Floor)"/>
        /// <seealso cref="HandleCallCageSignal(CallCageSignal)"/>
        /// </summary>
        /// <param name="signal">要处理的呼层呼梯信号</param>
        /// <returns>指示该信号是否被成功处理</returns>
        public virtual bool HandleCallSignal(ICallSignal signal)
        {
            var floor = Floors[signal.FloorId];
            switch (signal)
            {
                case CallCageSignal callCageSignal when callCageSignal.Direction == Direction.Up:       // 向上的呼梯信号
                    floor.CallUpButton.Press();
                    return HandleCallCageSignal(callCageSignal);
                case CallCageSignal callCageSignal when callCageSignal.Direction == Direction.Down:     // 向下的呼梯信号
                    floor.CallDownButton.Press();
                    return HandleCallCageSignal(callCageSignal);
                case CallFloorSignal callFloorSignal:                                                   // 呼层信号
                    var cage = Elevators[callFloorSignal.CageId];
                    return HandleCallFloorSignal(cage, floor);
                default:
                    return false;
            }
        }

        /// <summary>
        /// 处理呼梯信号的抽象方法，返回值指示该信号是否被成功处理。
        /// </summary>
        /// <param name="signal">呼梯信号</param>
        /// <returns>指示该信号是否被成功处理</returns>
        protected abstract bool HandleCallCageSignal(CallCageSignal signal);

        /// <summary>
        /// 处理呼层信号的方法，返回值指示该信号是否被成功处理。
        /// 特定子类可重写该方法，以扩展或覆盖该实现。
        /// </summary>
        /// <param name="signal">呼层信号</param>
        /// <returns>指示该信号是否被成功处理</returns>
        protected virtual bool HandleCallFloorSignal(Elevator elevator, Floor floor)
        {
            elevator.CallFloor(floor.Id);
            return true;
        }
        /// <summary>
        /// 清除指定楼层指定方向上的呼梯信号
        /// </summary>
        /// <param name="floorId">楼层 Id</param>
        /// <param name="direction">呼梯信号的方向</param>
        public virtual void EraseCallCageSignals(int floorId, Direction direction)
        {
            foreach (var elevator in Elevators)
            {
                elevator.ClearCallCageSignals(floorId, direction);
            }
        }
    }
}
